/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ecom.shell;

import ecom.ejb.AdminRemote;
import java.io.PrintStream;
import java.util.regex.Pattern;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import shell.command.ShellCommandImpl;
import shell.command.ShellContext;

import ecom.ejb.CustomerRemote;
import ecom.ejb.EuroConverterRemote;
import ecom.ejb.EuroConverterRemote.Devise;
import ecom.entity.ProductRemote;
import ecom.entity.ProductStoreRemote;
import exceptions.IdentifiantInvalide;
import exceptions.InstanceInvalide;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import shell.Shell;

/**
 *
 * @author François
 */
public class ProductCommandImpl extends ShellCommandImpl {
    /**
     * Constructeur
     */
    public ProductCommandImpl(ShellContext context) {
	super(context);
    }

    @Override
    public String getName() {
	return "product";
    }

    @Override
    public String getUsage() {
	return "product [ -store <int> | -name \"<string>\" | -like <string> | -price <int> [<int>] | \n    -create <long_id> <string_name> <double_price> <long_store> [<string_url>] | -delete <long> ]";
    }

    /**
     * @see shell.command.ShellCommand#getShortDescription()
     */
    @Override
    public String getShortDescription() {
	return "List of products";
    }

    /**
     * @see shell.command.ShellCommandImpl#execute(java.lang.String,
     *      java.io.PrintStream, java.io.PrintStream)
     */
    @Override
    public void execute(final String ligneDeCommande, final PrintStream out,
	    final PrintStream err) {
	/*
	 * L'id doit être un nombre
	 */
	Pattern patternStore = Pattern.compile("^-store\\s[0-9]+$");
	/*
	 * Le nom doit être entre guillemets et peut lui-même contenir des
	 * guillemets
	 */
	Pattern patternName = Pattern.compile("^-name\\s\".+\"$");
	/*
	 * Le motif peut être tout sauf un blanc
	 */
	Pattern patternLike = Pattern.compile("^-like\\s\\S+$");
	/*
	 * Le prix simple doit être un double
	 */
	Pattern patternPriceInf = Pattern
		.compile("^-price\\s((\\d+)|(\\d+\\.\\d+))$");
	/*
	 * Le double prix doit être composé de deux doubles séparés d'un espace
	 */
	Pattern patternPriceSupInf = Pattern
		.compile("^-price\\s((\\d+)|(\\d+\\.\\d+))\\s((\\d+)|(\\d+\\.\\d+))$");

	/*
	 * Création
	 */
	Pattern patternCreate = Pattern
	//	.compile("^-create\\s(\\d+)\\s(\\w+)\\s((\\d+)|(\\d+\\.\\d+))\\s(\\d+)(\\s(\\w*)){0,1}$");
		.compile("^-create\\s.*$");

	/*
	 * Suppression
	 */
	Pattern patternDelete = Pattern.compile("^-delete\\s(\\d+)$");

	/*
	 * Préparation de la sortie
	 */
	Document dom = null;
	Element root = null;
	StringBuilder texte = null;
	boolean erreur = false;

	if (this.getContexte().getVar(EcomShellConstantes.OUTPUT_MIME_FORMAT)
		.equals(EcomShellConstantes.TEXT_MIMETYPE)) {
	    /*
	     * Si TEXTE
	     */
	    texte = new StringBuilder();
	} else if (this.getContexte()
		.getVar(EcomShellConstantes.OUTPUT_MIME_FORMAT)
		.equals(EcomShellConstantes.XML_MIMETYPE)) {
	    /*
	     * Si XML
	     */
	    try {
		dom = Output.getNewDocument();
		root = dom.createElement(this.getName() + "Command");
		dom.appendChild(root);
	    } catch (final ParserConfigurationException e) {
		err.println(e.getMessage());
	    }
	}

	/*
	 * Aucun argument -> Liste
	 */
	if (ligneDeCommande.trim().equals("")) {
	    out.println("Affichage de tous les produits");

	    /*
	     * Récupération de la liste des produits
	     */
	    List<ProductRemote> produits = ((CustomerRemote) this
		    .getContexte().getVar(EcomShellConstantes.CUSTOMER))
		    .listProducts();

	    /*
	     * Affichage
	     */
	    if (produits != null) {
		out.println("Affichage des produits:");

		ProductRemote cr = null;
		Iterator<ProductRemote> it = produits.iterator();
		while (it.hasNext()) {
		    cr = it.next();
		    /*
		     * Gestion de la sortie
		     */
		    if (this.getContexte()
			    .getVar(EcomShellConstantes.OUTPUT_MIME_FORMAT)
			    .equals(EcomShellConstantes.TEXT_MIMETYPE)) {
			/*
			 * Si TEXTE
			 */
			texte.append("\t"
				+ Output
					.toString(
						cr,
						(Devise) this
							.getContexte()
							.getVar(EcomShellConstantes.CURRENT_CURRENCY),
						((EuroConverterRemote) this
							.getContexte()
							.getVar(EcomShellConstantes.CONVERTER)))
				+ Shell.RETOUR_CHARIOT);
		    } else if (this.getContexte()
			    .getVar(EcomShellConstantes.OUTPUT_MIME_FORMAT)
			    .equals(EcomShellConstantes.XML_MIMETYPE)) {
			/*
			 * Si XML
			 */
			root.appendChild(Output
				.toXml(cr,
					dom,
					(Devise) this
						.getContexte()
						.getVar(EcomShellConstantes.CURRENT_CURRENCY),
					((EuroConverterRemote) this
						.getContexte()
						.getVar(EcomShellConstantes.CONVERTER))));
		    }
		}
	    } else {
		out.println("Pas de produit à afficher");
	    }
	}
	/*
	 * Affichage des produits du magasin
	 */
	else if (patternStore.matcher(ligneDeCommande).find()) {
	    /*
	     * Extraction de l'id du magasin
	     */
	    Long referenceLong = Long.valueOf(ligneDeCommande.replace(
		    "-store ", ""));
	    out.println("Id du magasin à afficher : " + referenceLong);

	    /*
	     * Récupération du magasin
	     */
	    try {
		ProductStoreRemote magasin = ((CustomerRemote) this
			.getContexte().getVar(EcomShellConstantes.CUSTOMER))
			.getProductStore(referenceLong);

		/*
		 * Affichage des magasins
		 */
		ProductRemote cr = null;
		Iterator<ProductRemote> it = magasin.getProducts().iterator();
		while (it.hasNext()) {
		    cr = it.next();
		    /*
		     * Gestion de la sortie
		     */
		    if (this.getContexte()
			    .getVar(EcomShellConstantes.OUTPUT_MIME_FORMAT)
			    .equals(EcomShellConstantes.TEXT_MIMETYPE)) {
			/*
			 * Si TEXTE
			 */
			texte.append("\t"
				+ Output
					.toString(
						cr,
						(Devise) this
							.getContexte()
							.getVar(EcomShellConstantes.CURRENT_CURRENCY),
						((EuroConverterRemote) this
							.getContexte()
							.getVar(EcomShellConstantes.CONVERTER)))
				+ Shell.RETOUR_CHARIOT);
		    } else if (this.getContexte()
			    .getVar(EcomShellConstantes.OUTPUT_MIME_FORMAT)
			    .equals(EcomShellConstantes.XML_MIMETYPE)) {
			/*
			 * Si XML
			 */
			root.appendChild(Output
				.toXml(cr,
					dom,
					(Devise) this
						.getContexte()
						.getVar(EcomShellConstantes.CURRENT_CURRENCY),
					((EuroConverterRemote) this
						.getContexte()
						.getVar(EcomShellConstantes.CONVERTER))));
		    }
		}
	    } catch (final IdentifiantInvalide e) {
		err.println(e.getMessage());
	    }
	} else if (patternName.matcher(ligneDeCommande).find()) {
	    /*
	     * Extraction du nom du produit
	     */
	    String nom = ligneDeCommande.replace("-name ", "").replaceAll("\"",
		    "");
	    out.println("Nom du produit à afficher : " + nom);

	    /*
	     * Récupération de la liste des produits
	     */
	    List<ProductRemote> produits = ((CustomerRemote) this
		    .getContexte().getVar(EcomShellConstantes.CUSTOMER))
		    .listProducts();

	    ProductRemote cr = null;
	    Iterator<ProductRemote> it = produits.iterator();
	    while (it.hasNext()) {
		cr = it.next();
		if (cr.getName().toLowerCase(Locale.FRANCE)
			.equals(nom.toLowerCase(Locale.FRANCE))) {
		    /*
		     * Gestion de la sortie
		     */
		    if (this.getContexte()
			    .getVar(EcomShellConstantes.OUTPUT_MIME_FORMAT)
			    .equals(EcomShellConstantes.TEXT_MIMETYPE)) {
			/*
			 * Si TEXTE
			 */
			texte.append("\t"
				+ Output
					.toString(
						cr,
						(Devise) this
							.getContexte()
							.getVar(EcomShellConstantes.CURRENT_CURRENCY),
						((EuroConverterRemote) this
							.getContexte()
							.getVar(EcomShellConstantes.CONVERTER)))
				+ Shell.RETOUR_CHARIOT);
		    } else if (this.getContexte()
			    .getVar(EcomShellConstantes.OUTPUT_MIME_FORMAT)
			    .equals(EcomShellConstantes.XML_MIMETYPE)) {
			/*
			 * Si XML
			 */
			root.appendChild(Output
				.toXml(cr,
					dom,
					(Devise) this
						.getContexte()
						.getVar(EcomShellConstantes.CURRENT_CURRENCY),
					((EuroConverterRemote) this
						.getContexte()
						.getVar(EcomShellConstantes.CONVERTER))));
		    }
		}
	    }
	} else if (patternLike.matcher(ligneDeCommande).find()) {
	    /*
	     * Extraction du nom du produit
	     */
	    String nom = ligneDeCommande.replace("-like ", "").replace("%", "")
		    .replaceAll("\"", "");
	    out.println("Nom du produit à rechercher : " + nom);

	    /*
	     * Récupération de la liste des produits
	     */
	    List<ProductRemote> produits = ((CustomerRemote) this
		    .getContexte().getVar(EcomShellConstantes.CUSTOMER))
		    .listProducts();

	    ProductRemote cr = null;
	    Iterator<ProductRemote> it = produits.iterator();
	    while (it.hasNext()) {
		cr = it.next();
		if (cr.getName().toLowerCase(Locale.FRANCE)
			.contains(nom.toLowerCase(Locale.FRANCE))) {
		    /*
		     * Gestion de la sortie
		     */
		    if (this.getContexte()
			    .getVar(EcomShellConstantes.OUTPUT_MIME_FORMAT)
			    .equals(EcomShellConstantes.TEXT_MIMETYPE)) {
			/*
			 * Si TEXTE
			 */
			texte.append("\t"
				+ Output
					.toString(
						cr,
						(Devise) this
							.getContexte()
							.getVar(EcomShellConstantes.CURRENT_CURRENCY),
						((EuroConverterRemote) this
							.getContexte()
							.getVar(EcomShellConstantes.CONVERTER)))
				+ Shell.RETOUR_CHARIOT);
		    } else if (this.getContexte()
			    .getVar(EcomShellConstantes.OUTPUT_MIME_FORMAT)
			    .equals(EcomShellConstantes.XML_MIMETYPE)) {
			/*
			 * Si XML
			 */
			root.appendChild(Output
				.toXml(cr,
					dom,
					(Devise) this
						.getContexte()
						.getVar(EcomShellConstantes.CURRENT_CURRENCY),
					((EuroConverterRemote) this
						.getContexte()
						.getVar(EcomShellConstantes.CONVERTER))));
		    }
		}
	    }
	} else if (patternPriceInf.matcher(ligneDeCommande).find()) {
	    /*
	     * Extraction du prix inférieur
	     */
	    Double prix = Double.parseDouble(ligneDeCommande.replace("-price ",
		    ""));
	    out.println("Prix maximum à rechercher : " + prix);

	    /*
	     * Récupération de la liste des produits
	     */
	    List<ProductRemote> produits = ((CustomerRemote) this
		    .getContexte().getVar(EcomShellConstantes.CUSTOMER))
		    .listProducts();

	    ProductRemote cr = null;
	    Iterator<ProductRemote> it = produits.iterator();
	    while (it.hasNext()) {
		cr = it.next();
		if (cr.getPrice() <= prix) {
		    /*
		     * Gestion de la sortie
		     */
		    if (this.getContexte()
			    .getVar(EcomShellConstantes.OUTPUT_MIME_FORMAT)
			    .equals(EcomShellConstantes.TEXT_MIMETYPE)) {
			/*
			 * Si TEXTE
			 */
			texte.append("\t"
				+ Output
					.toString(
						cr,
						(Devise) this
							.getContexte()
							.getVar(EcomShellConstantes.CURRENT_CURRENCY),
						((EuroConverterRemote) this
							.getContexte()
							.getVar(EcomShellConstantes.CONVERTER)))
				+ Shell.RETOUR_CHARIOT);
		    } else if (this.getContexte()
			    .getVar(EcomShellConstantes.OUTPUT_MIME_FORMAT)
			    .equals(EcomShellConstantes.XML_MIMETYPE)) {
			/*
			 * Si XML
			 */
			root.appendChild(Output
				.toXml(cr,
					dom,
					(Devise) this
						.getContexte()
						.getVar(EcomShellConstantes.CURRENT_CURRENCY),
					((EuroConverterRemote) this
						.getContexte()
						.getVar(EcomShellConstantes.CONVERTER))));
		    }
		}
	    }
	} else if (patternPriceSupInf.matcher(ligneDeCommande).find()) {
	    /*
	     * Extraction du prix inférieur et supérieur
	     */
	    Double prixMin = Double.parseDouble(ligneDeCommande.replace(
		    "-price ", "").split(" ")[0]);
	    Double prixMax = Double.parseDouble(ligneDeCommande.replace(
		    "-price ", "").split(" ")[1]);
	    out.println("Prix compris entre : " + prixMin + " et " + prixMax);

	    /*
	     * Récupération de la liste des produits
	     */
	    List<ProductRemote> produits = ((CustomerRemote) this
		    .getContexte().getVar(EcomShellConstantes.CUSTOMER))
		    .listProducts();

	    ProductRemote cr = null;
	    Iterator<ProductRemote> it = produits.iterator();
	    while (it.hasNext()) {
		cr = it.next();
		if (cr.getPrice() <= prixMax && cr.getPrice() >= prixMin) {
		    /*
		     * Gestion de la sortie
		     */
		    if (this.getContexte()
			    .getVar(EcomShellConstantes.OUTPUT_MIME_FORMAT)
			    .equals(EcomShellConstantes.TEXT_MIMETYPE)) {
			/*
			 * Si TEXTE
			 */
			texte.append("\t"
				+ Output
					.toString(
						cr,
						(Devise) this
							.getContexte()
							.getVar(EcomShellConstantes.CURRENT_CURRENCY),
						((EuroConverterRemote) this
							.getContexte()
							.getVar(EcomShellConstantes.CONVERTER)))
				+ Shell.RETOUR_CHARIOT);
		    } else if (this.getContexte()
			    .getVar(EcomShellConstantes.OUTPUT_MIME_FORMAT)
			    .equals(EcomShellConstantes.XML_MIMETYPE)) {
			/*
			 * Si XML
			 */
			root.appendChild(Output
				.toXml(cr,
					dom,
					(Devise) this
						.getContexte()
						.getVar(EcomShellConstantes.CURRENT_CURRENCY),
					((EuroConverterRemote) this
						.getContexte()
						.getVar(EcomShellConstantes.CONVERTER))));
		    }
		}
	    }
	} else if (patternCreate.matcher(ligneDeCommande).find()) {
	    /*
	     * Extraction des arguments
	     */
	    String[] arguments = ligneDeCommande.replace("-create ", "").split(
		    " ");

	    try {

		/*
		 * Création du produit
		 */
		out.println("Création du produit");
		out.println("Référence : "
			+ Long.valueOf(arguments[0]).toString());
		out.println("Libellé : " + arguments[1]);
		out.println("Prix : " + Double.valueOf(arguments[2]).toString());
		out.println("Magasin : "
			+ Long.valueOf(arguments[3]).toString());
		out.println("Image : "
			+ (arguments.length > 4 ? arguments[4] : ""));

		ProductRemote produit = ((AdminRemote) this.getContexte()
			.getVar(EcomShellConstantes.ADMIN)).createProduct(Long
			.valueOf(arguments[0]), arguments[1], Double
			.valueOf(arguments[2]), Long.valueOf(arguments[3]),
			(arguments.length > 4 ? arguments[4] : ""));

		/*
		 * Gestion de la sortie
		 */
		if (this.getContexte()
			.getVar(EcomShellConstantes.OUTPUT_MIME_FORMAT)
			.equals(EcomShellConstantes.TEXT_MIMETYPE)) {
		    /*
		     * Si TEXTE
		     */
		    texte.append("\t"
			    + Output
				    .toString(
					    produit,
					    (Devise) this
						    .getContexte()
						    .getVar(EcomShellConstantes.CURRENT_CURRENCY),
					    ((EuroConverterRemote) this
						    .getContexte()
						    .getVar(EcomShellConstantes.CONVERTER)))
			    + Shell.RETOUR_CHARIOT);
		} else if (this.getContexte()
			.getVar(EcomShellConstantes.OUTPUT_MIME_FORMAT)
			.equals(EcomShellConstantes.XML_MIMETYPE)) {
		    /*
		     * Si XML
		     */
		    root.appendChild(Output.toXml(
			    produit,
			    dom,
			    (Devise) this.getContexte().getVar(
				    EcomShellConstantes.CURRENT_CURRENCY),
			    ((EuroConverterRemote) this.getContexte().getVar(
				    EcomShellConstantes.CONVERTER))));
		}
	    } catch (final NumberFormatException e) {
		err.println(e.getMessage());
	    } catch (final IdentifiantInvalide e) {
		err.println(e.getMessage());
	    } catch (final InstanceInvalide e) {
		err.println(e.getMessage());
	    }
	} else if (patternDelete.matcher(ligneDeCommande).find()) {
	    /*
	     * Extraction des arguments
	     */
	    String arguments = ligneDeCommande.replace("-delete ", "");

	    /*
	     * Création du compte
	     */
	    out.println("Suppression du produit " + arguments);

	    /*
	     * Récupération du compte
	     */
	    ProductRemote produit;
	    try {
		produit = ((AdminRemote) this.getContexte().getVar(
			EcomShellConstantes.ADMIN)).getProduct(Long
			.valueOf(arguments));

		((AdminRemote) this.getContexte().getVar(
			EcomShellConstantes.ADMIN)).removeProduct(produit);
	    } catch (final IdentifiantInvalide e) {
		err.println(e.getMessage());
	    }
	} else { 
	    out.println("Usage: " + this.getUsage());
	    erreur = true;
	}

	if (!erreur) {
	    /*
	     * Restitution de la sortie
	     */
	    if (this.getContexte()
		    .getVar(EcomShellConstantes.OUTPUT_MIME_FORMAT)
		    .equals(EcomShellConstantes.TEXT_MIMETYPE)) {
		/*
		 * Si TEXTE
		 */
		out.println(texte.toString());
	    } else if (this.getContexte()
		    .getVar(EcomShellConstantes.OUTPUT_MIME_FORMAT)
		    .equals(EcomShellConstantes.XML_MIMETYPE)) {
		try {
		    out.println(Output.toString(dom));
		} catch (final IOException e) {
		    err.println(e.getMessage());
		}
	    }
	}
    }
}

